package com.unit.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

public class ClassUtil {

	/**
	 * 第一层key为类名, 第二层key为fieldName，value为这field的Class
	 */
	private static Map<String, Map<String, Class<?>>> cacheForFieldClassMap = new ConcurrentHashMap<String, Map<String, Class<?>>>();
	private static Map<String, Set<String>> fieldNameMap = new ConcurrentHashMap<String, Set<String>>();

	public static Map<String, Class<?>> getFieldClassMap(Class<?> clazz) throws IntrospectionException {
		String className = clazz.getName();
		Map<String, Class<?>> fieldClassMap = cacheForFieldClassMap.get(className);
		if (fieldClassMap == null) {
			BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
			PropertyDescriptor[] descList = beanInfo.getPropertyDescriptors();
			fieldClassMap = new HashMap<String, Class<?>>();
			for (PropertyDescriptor desc : descList) {
				String fieldName = desc.getName();
				if (fieldName.equals("class") || fieldName.equals("attachBit")) {
					continue;
				}
				if (desc.getReadMethod() == null || desc.getWriteMethod() == null) {
					continue;
				}
				fieldClassMap.put(fieldName, desc.getPropertyType());
			}
		}
		cacheForFieldClassMap.put(className, fieldClassMap);
		return fieldClassMap;
	}

	public static Set<String> getFieldList(Class<?> clazz) throws IntrospectionException {
		String className = clazz.getName();
		Set<String> fieldList = fieldNameMap.get(className);
		if (fieldList == null) {
			fieldList = new CopyOnWriteArraySet<String>();
			BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
			PropertyDescriptor[] descList = beanInfo.getPropertyDescriptors();
			for (PropertyDescriptor desc : descList) {
				String fieldName = desc.getName();
				if (fieldName.equals("class") || fieldName.equals("attachBit")) {
					continue;
				}
				if (desc.getReadMethod() == null || desc.getWriteMethod() == null) {
					continue;
				}
				fieldList.add(fieldName);
			}
		}
		fieldNameMap.put(className, fieldList);
		return fieldList;
	}
}
